package com.chen.cloudpicture.manager.auth;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.chen.cloudpicture.manager.auth.model.SpaceUserAuthConfig;
import com.chen.cloudpicture.manager.auth.model.SpaceUserRole;
import com.chen.cloudpicture.model.entity.Space;
import com.chen.cloudpicture.model.entity.SpaceUser;
import com.chen.cloudpicture.model.entity.User;
import com.chen.cloudpicture.model.enums.SpaceRoleEnum;
import com.chen.cloudpicture.model.enums.SpaceTypeEnum;
import com.chen.cloudpicture.service.SpaceUserService;
import com.chen.cloudpicture.service.UserService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 全局空间成员权限管理
 * RBAC模型：用户角色权限以及两两关联的共五张表管理的权限控制模型。
 * 五张表太复杂，我们这里也没有这么多角色，可以用配置文件管理角色与权限，极大简化开发。
 *
 * 权限校验实现方案：最简单的方式就是写个注解 + AOP 切面。
 * 复杂角色权限管理可以使用第三方权限校验框架，如 Sa-token, spring security, shiro等。
 * 这里使用国内主流权限校验框架 Sa-token，它是轻量级的认证框架，文档写的比较全，实现也相对简单一些。
 * spring security 非常全面，有一系列过滤器链，要现在外层写一个登录过滤器完成登录验证再走security的过滤器链。
 * 主要要继承 UserDetailsService 重写 UserDetailsServiceImpl 类，在用户登录时加载用户权限等信息（然后还要写config配置类，还可以写认证/授权失败处理器等等）
 *
 * 过滤器与拦截器调用顺序：
 * 请求时：拦截器 -> 过滤器 -> 控制器
 * 响应时：控制器 -> 过滤器 -> 拦截器
 */
@Component
public class SpaceUserAuthManager {

    @Resource
    private UserService userService;
    @Resource
    private SpaceUserService spaceUserService;

    public static final SpaceUserAuthConfig SPACE_USER_AUTH_CONFIG;

    // final 修饰只能赋值一次，所以不能给 new 一个初始值，想修改只能重启项目
    static {
        // hutool 包的 ResourceUtil 帮助读取 resources 目录下的配置文件
        String s = ResourceUtil.readUtf8Str("biz/spaceUserAuthConfig.json");
        SPACE_USER_AUTH_CONFIG = JSONUtil.toBean(s, SpaceUserAuthConfig.class);
    }

    /**
     * 根据角色获取权限列表
     */
    public List<String> getPermissionsByRole(String spaceUserRole){
        if(StrUtil.isBlank(spaceUserRole))
            return new ArrayList<>();
        // 遍历角色权限列表
        SpaceUserRole role = SPACE_USER_AUTH_CONFIG.getRoles()
                .stream()
                .filter(r -> r.getKey().equals(spaceUserRole))
                .findFirst()
                .orElse(null);

        if(role == null)
            return new ArrayList<>();
        return role.getPermissions();
    }

    /**
     * 获取权限列表返回给前端，方便前端根据权限修改按钮的显示
     * （无需过多理会）
     */
    public List<String> getPermissionList(Space space, User loginUser) {
        if (loginUser == null) {
            return new ArrayList<>();
        }
        // 管理员权限
        List<String> ADMIN_PERMISSIONS = getPermissionsByRole(SpaceRoleEnum.ADMIN.getValue());
        // 公共图库
        if (space == null) {
            if (userService.isAdmin(loginUser)) {
                return ADMIN_PERMISSIONS;
            }
            return new ArrayList<>();
        }
        SpaceTypeEnum spaceTypeEnum = SpaceTypeEnum.getEnumByValue(space.getSpaceType());
        if (spaceTypeEnum == null) {
            return new ArrayList<>();
        }
        // 根据空间获取对应的权限
        switch (spaceTypeEnum) {
            case PRIVATE:
                // 私有空间，仅本人或管理员有所有权限
                if (space.getUserId().equals(loginUser.getId()) || userService.isAdmin(loginUser)) {
                    return ADMIN_PERMISSIONS;
                } else {
                    return new ArrayList<>();
                }
            case TEAM:
                // 团队空间，查询 SpaceUser 并获取角色和权限
                SpaceUser spaceUser = spaceUserService.lambdaQuery()
                        .eq(SpaceUser::getSpaceId, space.getId())
                        .eq(SpaceUser::getUserId, loginUser.getId())
                        .one();
                if (spaceUser == null) {
                    return new ArrayList<>();
                } else {
                    return getPermissionsByRole(spaceUser.getSpaceRole());
                }
        }
        return new ArrayList<>();
    }

}
